package com.pxst.fi.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pxst.constants.ResCodeContants;
import com.pxst.exception.BusinessException;
import com.pxst.fi.entity.SysAppHostEntity;
import com.pxst.fi.entity.SysBankCardFileEntity;
import com.pxst.fi.entity.SysThirdPartyConfigEntity;
import com.pxst.fi.entity.SysVpnEntity;
import com.pxst.fi.req.TpiDownloadReq;
import com.pxst.fi.req.TpiTransactionHistoryReq;
import com.pxst.fi.service.SysAppHostService;
import com.pxst.fi.service.SysBankCardFileService;
import com.pxst.fi.service.SysThirdPartyConfigService;
import com.pxst.fi.mapper.SysThirdPartyConfigMapper;
import com.pxst.fi.service.SysVpnService;
import com.pxst.resp.ApiResp;
import com.pxst.sys.req.ConfigRedisRsp;
import com.pxst.sys.service.SysConfigService;
import com.pxst.utils.HttpUtil;
import com.pxst.utils.RedisUtils;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.pxst.fi.constants.BankCardFileConstant.FILE_DESCRIPTION_TPI_VBS;
import static com.pxst.fi.constants.BankCardFileConstant.STATUS_PROCESSING;
import static com.pxst.fi.constants.RedisContant.*;

/**
* @author notch
* @description 针对表【sys_third_party_config(第三方支付配置（tpi100）)】的数据库操作Service实现
* @createDate 2023-09-25 15:41:15
*/
@Slf4j
@Service
public class SysThirdPartyConfigServiceImpl extends JoinServiceImpl<SysThirdPartyConfigMapper, SysThirdPartyConfigEntity>
    implements SysThirdPartyConfigService{

    @Autowired
    private SysBankCardFileService bankCardFileService;

    @Autowired
    private SysConfigService configService;

    @Autowired
    private SysVpnService vpnService;

    @Autowired
    private SysAppHostService appHostService;

    @Autowired
    private HttpUtil httpUtil;

    @Override
    public ApiResp download(TpiDownloadReq tpiDownloadReq) {
        // 将对象转换成treeMap按照属性名排序
        Field[] fields = tpiDownloadReq.getClass().getDeclaredFields();
        // 创建 TreeMap 存储属性名和属性值
        TreeMap<String, Object> treeMap = new TreeMap<>();
        for (Field field : fields) {
            field.setAccessible(true); // 设置属性可访问
            String fieldName = field.getName();
            Object fieldValue = null;
            try {
                fieldValue = field.get(tpiDownloadReq);
            } catch (IllegalAccessException e) {
                log.error("获取属性值失败，是姓名为：" + fieldName);
                e.printStackTrace();
                throw new BusinessException("获取属性值失败");
            }
            treeMap.put(fieldName, fieldValue);
        }
        // 生成md5值
        String hashQuery = DigestUtils.md5DigestAsHex(JSON.toJSONString(treeMap).getBytes());
        // 查询第三方支付配置（tpi100）表数据
        SysThirdPartyConfigEntity thirdPartyConfig = getOne(new LambdaQueryWrapper<SysThirdPartyConfigEntity>()
                .eq(SysThirdPartyConfigEntity::getDriver, tpiDownloadReq.getDriver()));
        if (ObjectUtils.isEmpty(thirdPartyConfig)) {
            throw new BusinessException("第三方支付设置数据不存在");
        }
        // 查询关联的银行卡流水帐汇出档案（LL120）的数据
        List<SysBankCardFileEntity> list = bankCardFileService.list(new LambdaQueryWrapper<SysBankCardFileEntity>()
                .eq(SysBankCardFileEntity::getThirdPartyConfigId, thirdPartyConfig.getId())
                .eq(SysBankCardFileEntity::getFileDescription, FILE_DESCRIPTION_TPI_VBS)
                .eq(SysBankCardFileEntity::getStatus, STATUS_PROCESSING));
        if (list.size() < 1) {
            throw new BusinessException("银行卡流水帐汇出档案数据不存在");
        }
        // 过滤参数不相同的数据
        List<SysBankCardFileEntity> collect = list.stream().filter(item -> {
            String hash = DigestUtils.md5DigestAsHex(item.getQueryParams().getBytes());
            return hash.equals(hashQuery);
        }).collect(Collectors.toList());
        // 判断同一参数的文件是否重复
        if (collect.size() > 0){
            Properties properties = new Properties();
            try{
                InputStream inputStream = this.getClass().getResourceAsStream("/i18n/message_vnpay.properties");
                properties.load(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return ApiResp.error(ResCodeContants.BUS_ERROR, properties.getProperty("download_duplicated"));
        }
        // 时区转化
        String timezone = configService.getSubCode(TIMEZONE, tpiDownloadReq.getDriver());
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        format.setTimeZone(TimeZone.getTimeZone(timezone));
        String startTime = format.format(tpiDownloadReq.getStartTime());
        String endTime = format.format(tpiDownloadReq.getEndTime());

        // 获取前缀
        String prefix = makePrefix();

        // 保存数据到银行卡流水帐汇出档案（LL120）
        SysBankCardFileEntity bankCardFile = new SysBankCardFileEntity();
        bankCardFile.setThirdPartyConfigId(thirdPartyConfig.getId());
        bankCardFile.setQueryParams(JSON.toJSONString(treeMap));
        bankCardFile.setFileDescription(FILE_DESCRIPTION_TPI_VBS);
        bankCardFile.setCommandId(prefix);
        bankCardFileService.save(bankCardFile);

        // 准备请求参数
        String currency = configService.getSubCode(TPI_CURRENCY, tpiDownloadReq.getDriver() + "Currency");
        Long vpnId = getActiveVPN(currency);
        // 获取主机地址
        String baseUri = getHostUrl(vpnId);
        // 创建发送参数类
        TpiTransactionHistoryReq tpiTransactionHistoryReq = new TpiTransactionHistoryReq();
        tpiTransactionHistoryReq.setReqid(prefix);
        tpiTransactionHistoryReq.setUserBank(driverToBank(tpiDownloadReq.getDriver()));
        tpiTransactionHistoryReq.setUsername(thirdPartyConfig.getAppId());
        // 获取meta_param的console_password值
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JsonNode jsonNode = objectMapper.readTree(thirdPartyConfig.getMetaParam());
            String password = jsonNode.get("console_password").asText();
            tpiTransactionHistoryReq.setPassword(password);
        } catch (JsonProcessingException e) {
            log.error("json格式化异常,字符串为：", thirdPartyConfig.getMetaParam());
            e.printStackTrace();
            throw new BusinessException("json格式化异常");
        }
        try {
            tpiTransactionHistoryReq.setFrom(format.parse(startTime));
            tpiTransactionHistoryReq.setTo(format.parse(endTime));
        } catch (ParseException e) {
            log.error("字符串转换Date异常，字符串为：" + startTime + "或则：" + endTime);
            e.printStackTrace();
            throw new BusinessException("字符串转换Date异常");
        }
        tpiTransactionHistoryReq.setVpnGroup(vpnId);
        tpiTransactionHistoryReq.setStatus(tpiDownloadReq.getStatus());
        // 发送请求
        httpUtil.doJsonPost(baseUri, JSON.toJSONString(tpiTransactionHistoryReq));

        return ApiResp.sucess();
    }

    /**
     * 获取主机地址
     * @param vpnId
     * @return
     */
    @Override
    public String getHostUrl(Long vpnId) {
        SysAppHostEntity appHost = appHostService.getById(vpnId);
        String baseUri = appHost.getBaseUri();
        return baseUri;
    }

    /**
     * 前端传入的值转换为对应的第三方银行
     * @param driver
     * @return
     */
    private String driverToBank(String driver) {
        Map<String, String> map = new HashMap<>();
        map.put("vnpay", "VNPAY");
        return map.get(driver);
    }

    /**
     * 根据地区获取VPN id
     *
     * @param currency
     * @return
     */
    private Long getActiveVPN(String currency) {
        // 获取vpnId范围
        String vpnKVND = configService.getSubCode("sys:config:vpnRange", "vpnKVND");
        String[] vpnKVNDRange = vpnKVND.split(",");
        SysVpnEntity vpn = vpnService.getOne(new LambdaQueryWrapper<SysVpnEntity>()
                .between(SysVpnEntity::getId, Integer.parseInt(vpnKVNDRange[0]), Integer.parseInt(vpnKVNDRange[1]))
                .eq(SysVpnEntity::getActive, 1)
        );
        return vpn.getId();
    }

    /**
     * 生成唯一的command_id
     * @return
     */
    private String makePrefix() {
        StringBuilder prefix = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            prefix.append("XS");
            prefix.append(RandomStringUtils.random(12, true, false));
            SysBankCardFileEntity one = bankCardFileService.getOne(new LambdaQueryWrapper<SysBankCardFileEntity>()
                    .eq(SysBankCardFileEntity::getCommandId, prefix));
            if (ObjectUtils.isEmpty(one)){
                return prefix.toString();
            }
        }
        throw new BusinessException("makePrefix failed");
    }
}




